package cn.com.flat.mybatis.plugins;

import cn.com.flat.mybatis.jdbc.dialect.Dialect;
import cn.com.flat.mybatis.jdbc.dialect.DialectHelper;
import cn.com.flat.mybatis.jdbc.util.MybatisSql;
import cn.com.flat.web.page.Page;

import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.DefaultReflectorFactory;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.springframework.util.StringUtils;


import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Map;
import java.util.Properties;

import static cn.com.flat.mybatis.jdbc.dialect.DialectHelper.getCurrentDialect;
import static sun.java2d.cmm.ColorTransform.In;

/**
 * 标题: Mybatis分页拦截器
 * <p>
 * 描述: Mybatis分页拦截器
 * <p>
 * 版权：Copyright (c) 2016
 * <p>
 *
 * @author 张顺
 * @version 1.0
 * @created 2016/11/06/19:11
 */
@Intercepts({
        @Signature(
                type= StatementHandler.class,
                method = "prepare",
                args = {Connection.class,Integer.class}
        )
})
public class MybatisPageInterceptor implements Interceptor{


    protected ThreadLocal<Page> pageThreadLocal = new ThreadLocal<Page>();

    /**
     * 拦截器要执行方法
     * @param invocation
     * @return
     * @throws Throwable
     */
    public Object intercept(Invocation invocation) throws Throwable {
        StatementHandler statementHandler = (StatementHandler)invocation.getTarget();
        MetaObject metaObject = MetaObject.forObject(statementHandler, SystemMetaObject.DEFAULT_OBJECT_FACTORY,
                SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY,new DefaultReflectorFactory());
        MappedStatement mappedStatement = (MappedStatement)metaObject.getValue("delegate.mappedStatement");
        String id = mappedStatement.getId();
        BoundSql boundSql = statementHandler.getBoundSql();

        Map<String,Object> params = (Map<String,Object>)boundSql.getParameterObject();
        Page pages = (Page)params.get("param2");
        if(!StringUtils.isEmpty(pages)){
            String sql = boundSql.getSql();
            String countSql = MybatisSql.buildCountSql(sql);
            Connection connection = (Connection)invocation.getArgs()[0];
            PreparedStatement countStatement = connection.prepareStatement(countSql);
            ParameterHandler parameterHandler = (ParameterHandler)metaObject.getValue("delegate.parameterHandler");
            parameterHandler.setParameters(countStatement);
            ResultSet rs = countStatement.executeQuery();
            if(rs.next()){
                pages.setTotalNumber(rs.getRow());
            }
            Dialect dialect;
            String pageSql   = (dialect = DialectHelper.getCurrentDialect()).getLimitString(sql,pages.getStartIndex(),pages.getTotalSelect());
            metaObject.setValue("delegate.bounSql.sql",pageSql);
        }
        return invocation.proceed();
    }

    /**
     * 拦截器需要拦截的对象
     * @param o
     * @return
     */
    public Object plugin(Object o) {
        return Plugin.wrap(o,this);
    }

    /**
     * 设置初始化属性值
     * @param properties
     */
    public void setProperties(Properties properties) {

    }
}
